/*
 * WebService.cpp
 *
 *  Created on: 2021年12月26日
 *      Author: vicent-PC
 */
#include "WebService.h"

#include <ArduinoOTA.h>
#include <ESPmDNS.h>
#include <WebServer.h>
#include <WiFi.h>

#include "WebCtrl.h"
#include "WebPage.h"
#include "c3log.h"
#include "esp_pm.h"
#include "esp_wifi.h"
#include "hal/motor/CommMotorManager.h"
#include "hal/motor/MotorManager.h"
#include "nvs_flash.h"
#include "Trace.h"

#define LOG_TAG "web_http_server"

WebService * WebService::m_pInstance = nullptr;

WebServer server(80);
const char* www_username = "kuailexingqiu";
const char* www_password = "yubao.zeng19910418";
int auth_sleep_s = 5;
int login_fail_cnt = 0;

int gStep = 0;

void cmdProc(String cmd) {
    LOGI("cmd:%s\n", cmd.c_str());
    String real_cmd = cmd.substring(1);  //"\1 \0"
    int cmd_num = real_cmd.toInt();
    MotorManager motorMgr;
    CommMotorManager commMotorMgr;
    int step = 0;

    // CTRL CMD process
    String stats = String("") + "Cmd:" + cmd_num + " Processing\n";
    switch (cmd_num) {
        case CMD_SOLENOID_ON:
            if (gStep <= 0)
                commMotorMgr.stepRun(1);
            else
                commMotorMgr.stepRun(gStep);
            break;
        case CMD_STEP_A365:
            step = -365;
            motorMgr.stepRun(abs(step), (step > 0));
            break;
        case CMD_STEP_365:
            step = 365;
            motorMgr.stepRun(abs(step), (step > 0));
            break;
        default:
            delay(10);  // 10ms
            break;
    }

    stats += String("") + "Cmd:" + cmd_num + " Done";
    // set step cmd process
    if (cmd_num >= CMD_SET_MOTOR_STEP_BASE &&
        cmd_num <= CMD_SET_MOTOR_STEP_MAX) {
        gStep = (cmd_num - CMD_SET_MOTOR_STEP_BASE) * 100;
        stats += String("") + " gStep:" + gStep;
    }
    server.send(200, "text/plain", stats);
}

class CustomRequestHandler : public RequestHandler {
   public:
    int id = 0;
    virtual ~CustomRequestHandler() {}
    virtual bool canHandle(HTTPMethod method, String uri) {
        (void)method;
        (void)uri;
        return true;
    }
    virtual bool handle(WebServer& server, HTTPMethod requestMethod,
                        String requestUri) {
        (void)server;
        if (!canHandle(requestMethod, requestUri)) return false;
        cmdProc(requestUri);
        // flag processed
        return true;
    }
};

RequestHandler* reqHandler = new CustomRequestHandler();  // must use new

int setupWeb() {
    ArduinoOTA.begin();
    server.on("/", []() {
        String stats;
        LOGI("visit web detect.");
        if (!server.authenticate(www_username, www_password)) {
            // login fail
            if (login_fail_cnt > 0) {
                auth_sleep_s += auth_sleep_s;
                if (auth_sleep_s > 300) auth_sleep_s = 300;
                stats = String("") + "wait:" + auth_sleep_s + " s";
                delay(auth_sleep_s * 1000);
            }
            login_fail_cnt++;
            return server.requestAuthentication();
        }
        if (server.hasArg("cmd")) {
            String cmd = server.arg("cmd");
            cmdProc(cmd);
            stats = stats + cmd;
            server.send(200, "text/html", stats);
            return;
        }
        server.send(200, "text/html", webLockPage);
        auth_sleep_s = 5;
        login_fail_cnt = 0;
    });

    server.on("/currentData", HTTP_POST,
              []() { server.send(200, "text/plain", String("") + rand()); });

    // server.addHandler(reqHandler);
    server.begin();
    return 0;
}

WebService::WebService() {
    // TODO Auto-generated constructor stub
}

// main loop
void webServerLoop(void* app) {
    while (1) {
        ArduinoOTA.handle();
        server.handleClient();
        // delay(10);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
    vTaskDelete(NULL);
}

int WebService::start() {
    int ret = setupWeb();
    if (ret != 0) {
        mStatus = WEB_WIFI_FAIL;
        return -1;
    }

    ret = xTaskCreate(webServerLoop,   /* Task function. */
                      "webServerLoop", /* String with name of task. */
                      8192,            /* Stack size in bytes. */
                      nullptr, /* Parameter passed as input of the task */
                      (configMAX_PRIORITIES - 1), /* Priority of the task. */
                      NULL);                      /* Task handle. */
    if (ret != pdPASS) {
        LOGE("Webserver xTaskCreate fail:%d", ret);
        mStatus = WEB_SERVER_FAIL;
    }
    return ret;
}

WebService::~WebService() {
}

int WebService::getRSSILevel() {
    return (100 + WiFi.RSSI()) / 11;
}
